<?php
/**
 *
 * @author ninetyseven.
 * @date 2023-03-29 0:12
 */

namespace App\Services;

use App\Enum\BalanceLogEnum;
use App\Enum\VillagerEnum;
use App\Enum\WalletsEnum;
use App\Models\VillagerUserModel;
use App\Models\WalletModel;
use Exception;
use Illuminate\Support\Facades\Log;

class WalletService
{
    /**
     * 新用户 - 创建钱包
     *
     * @param $user
     * @return void
     */
    public static function createUserWallet($user)
    {
        $data = [
            'user_id'       =>$user['id'],
            'user_type'     => VillagerEnum::USER_VILLAGER_TYPE,
            ];
        WalletModel::create($data);
    }
    /**
     * 扣减善行币
     *
     * @param $userId
     * @param $amount
     * @return int
     * @throws Exception
     */
    public static function deductSxcxCoin($userId, $amount): int
    {
        try {
            return self::_deductMoney($userId, '', WalletsEnum::WALLET_MONEY_TYPE_SXCX_COIN, $amount, '', 'sxcx_coin');
        }catch (Exception $e ){
            Log::error("扣减钱包失败,E=".$e->getMessage());
            throw new Exception("扣减钱包失败");
        }
    }
    /**
     * 冻结出行积分，并添加扣减log
     *
     * @param $userId
     * @param $referNo
     * @param $amountType
     * @param $amount
     * @param $memo
     * @return int
     * @throws Exception
     */
    public static function deductFrozenGycxAxd($userId, $referNo, $amountType, $amount, $memo): int
    {
        try {
            if ($amountType == WalletsEnum::WALLET_MONEY_TYPE_GYCX_AXD) $field = 'gycx_axd';
            else throw new Exception("扣款类型参数有误。");

            return self::_deductMoney($userId, $referNo, $amountType, $amount, $memo, $field);
        }catch (Exception $e ){
            throw new Exception("扣减出行积分失败");
        }
    }

    /**
     * 取消冻结出行积分，并添加返还log
     * @param $userId
     * @param $referNo
     * @param $amountType
     * @param $amount
     * @param $memo
     * @return int
     * @throws Exception
     */
    public static function paybackFrozenGycxAxd($userId, $referNo, $amountType, $amount, $memo): int
    {
        try {
            if($amountType== WalletsEnum::WALLET_MONEY_TYPE_GYCX_AXD) $field = 'gycx_axd';
            else throw new Exception("扣款类型参数有误。");

            return self::_paybackMoney($userId, $referNo, $amountType, $amount, $memo, $field);
        }catch (Exception $e ){
            throw new Exception("扣减出行积分失败");
        }
    }

    /**
     * @param $logData
     * @return int
     * @throws Exception
     */
    public static function addDeductFrozenBalanceLog($logData): int
    {
        return self::_addDeductFrozenBalanceLog($logData);
    }

    /**
     * @param $logData
     * @return int
     * @throws Exception
     */
    public static function addPaybackFrozenBalanceLog($logData): int
    {
        return self::_addPaybackFrozenBalanceLog($logData);
    }
    //=============================================================================================
    //                                      private function bellow
    //=============================================================================================
    /**
     * 扣减金额 并添加log
     * @param $userId
     * @param $referNo
     * @param $amountType
     * @param $amount
     * @param $memo
     * @param $field
     * @return int
     * @throws Exception
     */
    private static function _deductMoney($userId, $referNo, $amountType, $amount, $memo, $field): int
    {
        //  获取钱包
        $userWallet = WalletModel::query()->where(['user_id'=>$userId])->first();
        if( empty($userWallet)) throw new Exception("无法获取用户钱包。");

        // 验证数额
        if( $userWallet->$field < $amount )throw new Exception("用户钱包数额不足。");

        // 扣减金额
        $userWallet->$field -= $amount;
        if ($userWallet->save()){
            //有备注则添加，无则不添加
            if( !empty($memo) ) {
                // 添加log
                $result = self::_addDeductFrozenBalanceLog([
                    'order_no' => $referNo,
                    'user_id' => $userId,
                    'amount' => $amount,
                    'amount_type' => $amountType,
                    'comment' => $memo
                ]);
                if (empty($result)) throw new Exception("添加消费记录失败。");
                return $result;
            }else return 1;
        }else{
            throw new Exception("扣减用户钱包失败。");
        }
    }

    /**
     * 退还钱
     *
     * @param $userId
     * @param $referNo
     * @param $amountType
     * @param $amount
     * @param $memo
     * @param $field
     * @return int
     * @throws Exception
     */
    private static function _paybackMoney($userId, $referNo, $amountType, $amount, $memo, $field): int
    {
        //  获取钱包
        $userWallet = WalletModel::query()->where(['user_id'=>$userId])->first();
        if( empty($userWallet)) throw new Exception("无法获取用户钱包。");

        // 扣减金额
        $userWallet->$field += $amount;
        if ($userWallet->save()){
            // 添加log
            $result = self::_addPaybackFrozenBalanceLog([
                'order_no' => $referNo,
                'user_id' => $userId,
                'amount' => $amount,
                'amount_type'=> $amountType,
                'comment' => $memo
            ]);
            if( empty($result) )throw new Exception("添加返还记录失败。");
            return $result;
        }else{
            throw new Exception("返还用户钱包失败。");
        }
    }

    /**
     * @param $logData
     * @return int
     * @throws Exception
     */
    private static function _addDeductFrozenBalanceLog($logData): int
    {
        $logData['change_type'] = WalletsEnum::WALLET_LOG_TYPE_OUT;

        return self::_addFrozenBalance($logData);
    }

    /**
     * @param $logData
     * @return int
     * @throws Exception
     */
    private static function _addPaybackFrozenBalanceLog($logData): int
    {
        $logData['change_type'] = WalletsEnum::WALLET_LOG_TYPE_IN;

        return self::_addFrozenBalance($logData);
    }
    private static function _addFrozenBalance($logData): int
    {
        try {
            $logData['order_type'] = BalanceLogEnum::ORDER_TYPE_FROZEN;

            return CommonService::recordAmountLog($logData);
        }catch (Exception $e ){
            throw new Exception("添加冻结失败".$e->getMessage());
        }
    }
}
